home *** CD-ROM | disk | FTP | other *** search
/ Java Programmer's Toolkit / Java Programmer's Toolkit.iso / applets / dance / classes / sound.jav < prev    next >
Encoding:
Text File  |  1995-10-11  |  5.8 KB  |  277 lines

  1. /*-
  2.  * Copyright (c) 1995 by Georg Hessmann.
  3.  * All Right Reserved.
  4.  *
  5.  * Sound.java    1.0  25 Aug 1995
  6.  *        1.1  13 Sep 1995
  7.  *
  8.  */
  9.  
  10. import java.io.InputStream;
  11. import java.lang.Runnable;
  12. import java.lang.Thread;
  13. import java.net.URL;
  14. import java.awt.Graphics;
  15. import java.awt.Image;
  16. import java.awt.image.*;
  17. import java.applet.AudioClip;
  18.  
  19. import Dance;
  20.  
  21. /**
  22.  * Sound implements the thread, which is playing the sound and
  23.  * updating the takt (time) numbers. It also calls every time
  24.  * step java.applet.Applet.repaint().
  25.  *
  26.  * @see Dance
  27.  *
  28.  * @version 1.1  13 Sep 1995
  29.  * @author Georg Heßmann
  30.  */
  31. class Sound implements Runnable, ImageObserver {
  32.  
  33.   Dance app;
  34.  
  35.   AudioClip  audio     = null;
  36.   URL        audioURL;
  37.  
  38.   int Counter;
  39.   static Image numbers[];
  40.  
  41.   Image lastNumImg = null;    // letzte gezeichnete Nummer
  42.  
  43.   /** Maximal size().width of the takt numbers. */
  44.   public int numMaxW;
  45.   /** Maximal size().height of the takt numbers. */
  46.   public int numMaxH;
  47.  
  48.   Thread  pthread;
  49.   boolean StopIt;    // wenn true, dann beendet sich der Sound
  50.   // boolean StopItAfter;    // spiele den Sound noch einen Takt lang
  51.   
  52.  
  53.   /**
  54.    * Creates the sound object.
  55.    * If Dance.useAudio() is set, it preloads the audio data defined
  56.    * by the URL.
  57.    * @param audioURL pointer to the audio data
  58.    * @param app pointer to the main applet.
  59.    */
  60.   public Sound(URL audioURL, Dance app)
  61.   {
  62.     this.audioURL = audioURL;
  63.     this.app      = app;
  64.  
  65.     Counter = -1;
  66.  
  67.     numMaxW = 32;
  68.     numMaxH = 60;
  69.  
  70.     if (numbers == null) {
  71.       numbers = new Image[4];
  72.       for (int i=0; i<4; i++) {
  73.     numbers[i] = app.getImage(app.getCodeBase(),
  74.                   "images/nums-" + (i+1) + ".gif");
  75.     if (numbers[i].getWidth(this) >numMaxW) numMaxW = numbers[i].getWidth(this);
  76.     if (numbers[i].getHeight(this)>numMaxH) numMaxH = numbers[i].getHeight(this);
  77.       }
  78.     }
  79.  
  80.     if (app.useAudio() && audioURL != null) {
  81.       // preload audio data into browser cache
  82.       audio = app.getAudioClip(audioURL);
  83.     }
  84.     audio = null;
  85.   }
  86.  
  87.   /**
  88.    * Start the sound thread.
  89.    */
  90.   public synchronized void StartSound()
  91.   {
  92.     if (pthread != null) {
  93.       StopSound();
  94.     }
  95.     Counter = 0;
  96.     StopIt = false;
  97.     
  98.     pthread = new Thread(this, "Sound");
  99.     pthread.start();
  100.     pthread.setPriority(Thread.MAX_PRIORITY-1);
  101.  
  102.     if (audio != null) audio.stop();
  103.     audio = null;
  104.     
  105.     if (app.useAudio() && audioURL != null) {
  106.       audio = app.getAudioClip(audioURL);
  107.     }
  108.     
  109.     if (audio != null) audio.play();
  110.   }
  111.  
  112.   /**
  113.    * Delete the sound thread.
  114.    */
  115.   public synchronized void KillSound()
  116.   {
  117.     if (pthread != null) {
  118.       if (pthread.isAlive()) pthread.stop();
  119.       pthread = null;
  120.       Counter = -1;    // hide counter box
  121.     }
  122.     if (audio != null) {
  123.       audio.stop();
  124.       audio = null;
  125.     }
  126.   }
  127.  
  128.   /**
  129.    * Stop the Sound thread.
  130.    */
  131.   public void StopSound()
  132.   {
  133.     StopIt = true;
  134.   }
  135.  
  136.   /**
  137.    * Test if the sound thread is still alive.
  138.    */
  139.   public boolean SoundAlive()
  140.   {
  141.     return (pthread != null);
  142.   }
  143.  
  144.   /**
  145.    * Main function of the sound thread.
  146.    * Sleeps one timestep, update the takt counter and does a repaint.
  147.    * Runs until StopSound() or KillSound() is called.
  148.    */
  149.   public void run()
  150.   {
  151.     try {
  152.       Thread.sleep(100);    // 1/10'tel hinter den anderen Threads laufen
  153.     } catch (InterruptedException e) {
  154.       return;
  155.     }
  156.     
  157.     long wtime;                    // wait time in millis
  158.     long stime = System.currentTimeMillis();    // start time in millis
  159.     long ctime;                    // current time in millis
  160.  
  161.     wtime = 1000 * 60 / app.figur.BPM;
  162.  
  163.     while (!StopIt) {
  164.       Counter++;
  165.       app.repaint();
  166.       ctime = System.currentTimeMillis();
  167.       try {
  168.     Thread.sleep(wtime - (ctime-stime));
  169.       } catch (InterruptedException e) {
  170.     break;
  171.       }
  172.       stime = System.currentTimeMillis();
  173.     }
  174.     Counter = -1;
  175.  
  176.     if (audio != null) {
  177.       audio.stop();
  178.       audio = null;
  179.     }
  180.  
  181.     if (app.figur != null) {
  182.       app.figur.HideComStr();
  183.       app.repaint();
  184.     }
  185.     
  186.     pthread = null;
  187.   }
  188.  
  189.   /**
  190.    * Set the takt/time counter to c.
  191.    * Needed for the single step mode.
  192.    */
  193.   public void SetCounter(int c)
  194.   {
  195.     Counter = c;
  196.   }
  197.  
  198.   /**
  199.    * Get the number image suitable to the Counter value
  200.    * and the number of beats for one takt of the current dance.
  201.    */
  202.   public Image GetNumImg()
  203.   {
  204.     if (Counter > 0) {
  205.       return numbers[(Counter-1) % app.figur.Takte];
  206.     }
  207.     else return null;
  208.   }
  209.  
  210.  
  211.   /**
  212.    * Set last painted number.
  213.    * @see Figur#drawNum
  214.    */
  215.   public void setLastNumImg(Image img)
  216.   {
  217.     lastNumImg = img;
  218.   }
  219.  
  220.   /**
  221.    * Returns the last drawn image.
  222.    * @see Figur#drawNum
  223.    */
  224.   public Image getLastNumImg()
  225.   {
  226.     return lastNumImg;
  227.   }
  228.  
  229.   /**
  230.    * Manages infos about the number-images.
  231.    * @see ImageObserver#imageUpdate
  232.    */
  233.   public boolean imageUpdate(Image img,
  234.                  int infoflags, int x, int y,
  235.                  int width, int height)
  236.   {
  237.     // hier geht es um die Nummern
  238.     boolean ret     = true;
  239.     boolean dopaint = false;
  240.  
  241.     long updatetime = 0;    // sofort
  242.  
  243.     if ((infoflags & WIDTH) != 0) {
  244.       if (width  > numMaxW) numMaxW = width;
  245.     }
  246.     if ((infoflags & HEIGHT) != 0) {
  247.       if (height > numMaxH) numMaxH = height;
  248.     }
  249.     
  250.     if ((infoflags & (FRAMEBITS | ALLBITS)) != 0) {
  251.       dopaint = true;
  252.       ret     = false;
  253.     }
  254.     else if ((infoflags & SOMEBITS) != 0) {
  255.       dopaint    = true;
  256.       updatetime = 100;
  257.     }
  258.     
  259.     if ((infoflags & ERROR) != 0) {
  260.       ret = false;
  261.     }
  262.  
  263.     if (dopaint) {
  264.       if (lastNumImg == img) {
  265.     lastNumImg = null;    // force repaint
  266.       }
  267.       app.repaint(updatetime);
  268.     }
  269.  
  270.     return ret;
  271.   }
  272.  
  273. }
  274.  
  275.  
  276.  
  277.